package com.gm.wj.service;

import com.gm.wj.config.RedisConfig;
import com.gm.wj.dao.JotterArticleDAO;
import com.gm.wj.entity.JotterArticle;
import com.gm.wj.redis.RedisService;
import com.gm.wj.util.MyPage;
import com.gm.wj.util.MyTime;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author Evan
 * @date 2020/1/14 21:00
 */

/**
    * @program: wj
    * @description: 文章管理
    * @author: Huang_shengjun
    * @create: 2020-08-31 23:45
**/
@Service
@Slf4j
public class JotterArticleService {
    @Autowired
    JotterArticleDAO jotterArticleDAO;
    @Autowired
    RedisService redisService;
    @Autowired
    AdminPermissionService adminPermissionService;
    @Autowired
    PermissionURL permissionURL;

    public MyPage list(int page, int size) {
        MyPage<JotterArticle> articles;
        // 文章list缓存
        String key = "articlepage:" + page;
        Object articlePageCache = redisService.get(key);

        // 如果为空，就再查询一次，写入redis缓存
        if (articlePageCache == null) {
            Sort sort = Sort.by(Sort.Direction.DESC, "id");
            Page<JotterArticle> articlesInDb = jotterArticleDAO.findAll(PageRequest.of(page, size, sort));
            articles = new MyPage<>(articlesInDb);
            redisService.set(key, articles,5);
        } else {
            articles = (MyPage<JotterArticle>) articlePageCache;
        }
        return articles;
    }

    public MyPage listAdmin(int page, int size) {
        // 获取操作用户名
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        MyPage<JotterArticle> articles;
        // 文章list缓存
        String key =  username + "articlepage:" + page;
        Object articlePageCache = redisService.get(key);

        // 如果为空，就再查询一次，写入redis缓存
        if (articlePageCache == null) {
            Sort sort = Sort.by(Sort.Direction.DESC, "id");

            // 重写 findAll方法  多条件查询

            Pageable pageable = new PageRequest(page, size,sort);
            Page<JotterArticle> articlesInDb = jotterArticleDAO.findAll((Specification<JotterArticle>) (root, criteriaQuery, criteriaBuilder) -> {
                List<Predicate> list = new ArrayList<>();
                // 实体类字段，不是数据库字段
                list.add(criteriaBuilder.equal(root.get("username").as(String.class), username));
                // 如果拥有权限  清除只能查询自己的数据的条件查询
                if(permissionURL.isPermissionURL(JotterArticle.class.getSimpleName(),username)){
                    list.removeAll(list);
                }
                javax.persistence.criteria.Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            },pageable);
            // findAll方法 重写结束

            articles = new MyPage<>(articlesInDb);
            redisService.set(key, articles, RedisConfig.DATA_REDIS_KEY_TIME);
        } else {
            articles = (MyPage<JotterArticle>) articlePageCache;
        }
        return articles;
    }

//    用于复现异常
//    @Cacheable(value = RedisConfig.REDIS_KEY_DATABASE)
//    public Page list(int page, int size) {
//        Sort sort = new Sort(Sort.Direction.DESC, "id");
//        return jotterArticleDAO.findAll(PageRequest.of(page, size, sort));
//    }


    public JotterArticle findById(int id) {
        JotterArticle article;
        String key = "article:" + id;
        Object articleCache = redisService.get(key);

        if (articleCache == null) {
            article = jotterArticleDAO.findById(id);
            redisService.set(key, article,RedisConfig.DATA_REDIS_KEY_TIME);
        } else {
            article = (JotterArticle) articleCache;
        }
        return article;
    }

    public void addOrUpdate(JotterArticle article) {
        JotterArticle article1 = findById(article.getId());

        if (article1 == null){
            article.setCreateTime(MyTime.getStringDate());
        } else {
            article.setCreateTime(article1.getCreateTime());
        }
        jotterArticleDAO.save(article);

        redisService.delete("article" + article.getId());
        Set<String> keys = redisService.getKeysByPattern("articlepage*");
        redisService.delete(keys);
    }

    public void delete(int id) {
        jotterArticleDAO.deleteById(id);

        redisService.delete("article:" + id);
        Set<String> keys = redisService.getKeysByPattern("articlepage*");
        redisService.delete(keys);
    }
}
